package com.ztesoft.book.common.utils.redis;

import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.util.Set;
import java.util.concurrent.TimeUnit;


/**
 * @Description Redis工具类
 * @Author YangFan
 * @Date 2021-06-22 17:26
 */
@Component
public class RedisUtils {
    private static RedisTemplate<String, Object> redisTemplate;
    private static ValueOperations<String, String> valueOperations;

    @Autowired
    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        setRedisTemplateValue(redisTemplate);
    }
    public static void setRedisTemplateValue(RedisTemplate<String, Object> redisTemplate) {
        RedisUtils.redisTemplate = redisTemplate;
    }

    @Autowired
    public void setValueOperations(ValueOperations<String, String> valueOperations) {
        setValueOperationsValue(valueOperations);
    }
    public static void setValueOperationsValue(ValueOperations<String, String> valueOperations) {
        RedisUtils.valueOperations = valueOperations;
    }

    /**
     * 默认过期时长，单位：秒
     */
    public static final long DEFAULT_EXPIRE = 60 * 60 * 24;
    /**
     * 不设置过期时长
     */
    public static final long NOT_EXPIRE = -1;

    public static void setObject(String key, Object value, long expire) {
        redisTemplate.opsForValue().set(key, value);
        if (expire != NOT_EXPIRE) {
            redisTemplate.expire(key, expire, TimeUnit.SECONDS);
        }
    }


    public static void set(String key, Object value, long expire) {
        valueOperations.set(key, toJson(value));
        if (expire != NOT_EXPIRE) {
            redisTemplate.expire(key, expire, TimeUnit.SECONDS);
        }
    }

    public static void set(String key, Object value) {
        set(key, value, DEFAULT_EXPIRE);
    }

    public static <T> T get(String key, Class<T> clazz, long expire) {
        String value = valueOperations.get(key);
        if (expire != NOT_EXPIRE) {
            redisTemplate.expire(key, expire, TimeUnit.SECONDS);
        }
        return value == null ? null : fromJson(value, clazz);
    }

    public static <T> T get(String key, Class<T> clazz) {
        return get(key, clazz, NOT_EXPIRE);
    }

    public static String get(String key, long expire) {
        String value = valueOperations.get(key);
        if (expire != NOT_EXPIRE) {
            redisTemplate.expire(key, expire, TimeUnit.SECONDS);
        }
        return value;
    }

    public static Object getObject(String key) {
        Object object = redisTemplate.opsForValue().get(key);
        return object;
    }

    public static String get(String key) {
        return get(key, NOT_EXPIRE);
    }

    public static void delete(String key) {
        redisTemplate.delete(key);
    }

    public static Boolean exists(final String key) {
        return redisTemplate.hasKey(key);
    }


    public static void clearAll() {
        Set<String> keys = redisTemplate.keys("*");
        redisTemplate.delete(keys);
    }


    public static int size() {
        Set<String> keys = redisTemplate.keys("*");
        return keys.size();
    }


    public static Set<String> keys() {
        return redisTemplate.keys("*");
    }


    /**
     * 方法功能描述:
     * < 获取Key的过期时间     -1：永久   -2：无该值   其他表示剩余时间 >
     *
     * @param key 【参数 1 注释说明】
     * @return Long                            【返回值 注释说明】
     * @author YangFan
     * @date 2021-06-21 21:32
     */
    public static Long getExpire(String key) {
        return redisTemplate.getExpire(key);
    }

    /**
     * 方法功能描述:
     * < 重新设置redis键值的有效期，延期用 >
     *
     * @param key  【参数 1 注释说明】
     * @param time 【参数 2 注释说明】
     * @return void                            【返回值 注释说明】
     * @author YangFan
     * @date 2021-06-22 14:40
     */
    public static void resetExpire(String key, Long time) {
        redisTemplate.expire(key, time, TimeUnit.SECONDS);
    }


    /**
     * 方法功能描述:
     * < Object转成JSON数据 >
     *
     * @param object 【参数 1 注释说明】
     * @return String                        【返回值 注释说明】
     * @author YangFan
     * @date 2021-06-22 17:27
     */
    private static String toJson(Object object) {
        if (object instanceof Integer || object instanceof Long || object instanceof Float ||
                object instanceof Double || object instanceof Boolean || object instanceof String) {
            return String.valueOf(object);
        }
        return JSON.toJSONString(object);
    }


    /**
     * 方法功能描述:
     * < JSON数据，转成Object >
     *
     * @param json  【参数 1 注释说明】
     * @param clazz 【参数 2 注释说明】
     * @return T                            【返回值 注释说明】
     * @author YangFan
     * @date 2021-06-22 17:27
     */
    private static <T> T fromJson(String json, Class<T> clazz) {
        return JSON.parseObject(json, clazz);
    }

}
